<?php

namespace App\Http\Controllers\FixedCost;

use App\Http\Controllers\Controller;
use App\Models\Bus\Bus;
use App\Models\FixedCost\FixedCost;
use App\Models\FixedCost\FixedCostBus;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class FixedCostController extends Controller
{
    public function fixedCostList(Request $request)
    {
        $params = $countParams = $request->all();
        unset($countParams['pageNumber'], $countParams['pageSize']);

        $data = $this->getFixedCostList($params)
            ->orderByDesc('created_at')
            ->get()
            ->toArray();
        if ($data) {
            $data = $this->transData($data);
        }
        $dataCount = $this->getFixedCostList($countParams)->count();

        return response()->formatJson(['fixedCostList' => $data, 'count' => $dataCount]);
    }

    public function getFixedCostList($params): \Illuminate\Database\Eloquent\Builder
    {
        $query = FixedCost::query()->with('bus');

        if (isset($params['pageNumber'], $params['pageSize'])) {
            $query
                ->limit($params['pageSize'])
                ->offset(($params['pageNumber'] - 1) * $params['pageSize']);
        }

        return $query;
    }

    /**
     * 数据转化
     *
     * @param  array  $data
     *
     * @return array
     */
    public function transData(array $data): array
    {
        $objectType = [
            '全部车辆',
            '按车辆类型',
            '按车辆品牌',
            '自定义车辆',
        ];
        foreach ($data as $key => $cost) {
            $data[$key]['busCount'] = !empty($cost['bus']) ? count($cost['bus']) : 0;
            $data[$key]['object'] = $objectType[$cost['object_type']];
        }

        return $data;
    }

    /**
     * 创建车辆信息
     *
     * @param  Request  $request
     *
     * @return mixed
     */
    public function store(Request $request)
    {
        $params = $request->all();
        $fixedCost = new FixedCost($params);
        $result = $fixedCost->save();
        $message = $result ? '添加成功' : '添加失败';

        if ((int) $params['object_type'] === 0) {
            $bus = Bus::query()->pluck('license_plate_num')->toArray();
        } elseif ((int) $params['object_type'] === 1) {
            $bus = Bus::query()->where('type', $params['bus_type'])->pluck('license_plate_num')->toArray();
        } elseif ((int) $params['object_type'] === 2) {
            $bus = Bus::query()->where('brand', $params['bus_brand'])->pluck('license_plate_num')->toArray();
        } else {
            $bus = explode(',', $params['depIds']);
        }

        $busInsert = [];
        foreach ($bus as $v) {
            $busInsert[] = ['license_plate_num' => str_replace('陕G', '', $v)];
        }

        if ($busInsert) {
            foreach ($busInsert as $v) {
                $fixedCostBus = new FixedCostBus($v);
                $fixedCost->bus()->save($fixedCostBus);
            }
        }

        return response()->formatJson($result, $message);
    }

    public function edit($id)
    {
        $cost = FixedCost::query()->with('bus')->where('id', $id)->first()->toArray();

        $bus = array_column($cost['bus'], 'license_plate_num');

        $lastDate = DB::table('akbus_bus_distribution')->groupBy('date')->orderByDesc('date')->first();
        $lastVersion = DB::table('akbus_bus_distribution')->where('date', $lastDate['date'])->get()->toArray();
        $lastArr = collect($lastVersion)->groupBy('line')->toArray();

        $keys = array_keys($lastArr);
        $sortKey = bubbleSort($keys);

        $sortArr = [];
        foreach ($sortKey as $k => $v) {
            $sortArr[$v] = $lastArr[$v];
        }

        $tree = [];
        foreach ($sortArr as $k => $v) {
            $line = [];
            $line['title'] = $k !== 0 ? $k . '路' : '停运';
            $line['expand'] = false;
            $children = [];
            foreach ($v as $vv) {
                $child = [];
                $child['title'] = '陕G' . $vv['license_plate_num'];
                $child['expand'] = false;
                $child['license_plate_num'] = $vv['license_plate_num'];
                if ($bus && $cost['object_type'] === 3) {
                    $child['checked'] = in_array($vv['license_plate_num'], $bus, true);
                }
                $children[] = $child;
            }
            $line['children'] = $children;
            $tree[] = $line;
        }

        return response()->formatJson(['formData' => $cost, 'treeData' => $tree]);
    }

    /**
     * 修改文章
     *
     * @param  Request  $request
     * @param           $id
     *
     * @return mixed
     */
    public function update(Request $request, $id)
    {
        $params = $request->all();
        $fixedCost = FixedCost::query()->find($id);
        $params['start_at'] = date('Y-m-d', strtotime($params['start_at']));
        $params['end_at'] = date('Y-m-d', strtotime($params['end_at']));

        $result = $fixedCost->update($params);

        // 删除关联数据
        $fixedCost->bus()->delete();

        if ((int) $params['object_type'] === 0) {
            $bus = Bus::query()->pluck('license_plate_num')->toArray();
        } elseif ((int) $params['object_type'] === 1) {
            $bus = Bus::query()->where('type', $params['bus_type'])->pluck('license_plate_num')->toArray();
        } elseif ((int) $params['object_type'] === 2) {
            $bus = Bus::query()->where('brand', $params['bus_brand'])->pluck('license_plate_num')->toArray();
        } else {
            $bus = explode(',', $params['depIds']);
        }

        $busInsert = [];
        foreach ($bus as $v) {
            $busInsert[] = ['license_plate_num' => str_replace('陕G', '', $v)];
        }

        if ($busInsert) {
            foreach ($busInsert as $v) {
                $fixedCostBus = new FixedCostBus($v);
                $fixedCost->bus()->save($fixedCostBus);
            }
        }
        $message = $result ? '修改成功' : '修改失败';

        return response()->formatJson($result, $message);
    }

    /**
     * 删除车辆信息
     *
     * @param  Request  $request
     *
     * @return mixed
     */
    public function destroy(Request $request)
    {
        $result = false;
        if ($request->has('ids')) {
            $ids = explode(',', $request['ids']);
            $count = FixedCost::destroy($ids);
            $result = $count !== 0;
        }

        $message = $result ? '删除成功' : '删除失败';

        return response()->formatJson($result, $message);
    }

    public function fixedCostTree(Request $request)
    {
        $params = $request->all();
        if (isset($params['time']) && !empty($params['time']) && $params['time'] !== '2019') {
            $title = 'fixedCostTree_' . $params['time'];
        } else {
            $title = 'fixedCostTree';
        }
        return response()->formatJson(option($title));
    }

    public function editFixedCostTree(Request $request)
    {
        $params = $request->all();
        if (isset($params['time']) && !empty($params['time']) && $params['time'] !== '2019') {
            $title = 'fixedCostTree_' . $params['time'];
        } else {
            $title = 'fixedCostTree';
        }
        $tree = option($title);

        foreach ($tree as $key => $value) {
            if ($value['key'] === $params['key']) {
                $tree[$key]['title'] = $params['title'];
                $tree[$key]['type'] = $params['title'];
                continue;
            }
            if (isset($value['children'])) {
                foreach ($value['children'] as $k => $v) {
                    if ($v['key'] === $params['key']) {
                        $tree[$key]['children'][$k]['title'] = $params['title'];
                        $tree[$key]['children'][$k]['type'] = $params['title'];
                        continue;
                    }
                }
            }
        }

        option([$title => $tree]);

        return response()->formatJson(true);
    }

    public function updateFixedCostTree(Request $request)
    {
        $params = $request->all();
        if (isset($params['time']) && !empty($params['time']) && $params['time'] !== '2019') {
            $title = 'fixedCostTree_' . $params['time'];
        } else {
            $title = 'fixedCostTree';
        }
        $data = $params['data'];
        option([$title => $data]);

        return response()->formatJson(true);
    }

    public function destroyFixedCostTree(Request $request)
    {
        $params = $request->all();
        if (isset($params['time']) && !empty($params['time']) && $params['time'] !== '2019') {
            $title = 'fixedCostTree_' . $params['time'];
        } else {
            $title = 'fixedCostTree';
        }
        $removeKey = $params['ids'];
        $tree = option($title);

        foreach ($tree as $key => $value) {
            if ($value['key'] === $removeKey) {
                unset($tree[$key]);
                continue;
            }
            if (isset($value['children'])) {
                foreach ($value['children'] as $k => $v) {
                    if ($v['key'] === $removeKey) {
                        unset($tree[$key]['children'][$k]);
                        continue;
                    }
                }
            }
        }

        $tree = $this->rebuildKeys($tree);

        option([$title => $tree]);

        return response()->formatJson(true);
    }

    public function addFixedCostTree(Request $request)
    {
        $params = $request->all();
        if (isset($params['time']) && !empty($params['time']) && $params['time'] !== '2019') {
            $title = 'fixedCostTree_' . $params['time'];
        } else {
            $title = 'fixedCostTree';
        }
        $tree = option($title);

        foreach ($tree as $key => $value) {
            if ($value['key'] === $params['parentKey']) {
                if (isset($value['children']) && $value['children'] !== []) {
                    $lastKey = $value['children'][count($value['children']) - 1]['key'];
                    $keyArray = explode('-', $lastKey);
                    $keyArray[count($keyArray) - 1]++;
                    $newKey = implode('-', $keyArray);
                    $tree[$key]['children'][count($value['children'])] = [
                        'title'  => $params['title'],
                        'type'   => $params['title'],
                        'amount' => '',
                        'note'   => '',
                        'key'    => $newKey,
                    ];
                } else {
                    $tree[$key]['children'][] = [
                        'title'  => $params['title'],
                        'type'   => $params['title'],
                        'amount' => '',
                        'note'   => '',
                        'key'    => $value['key'] . '-1',
                    ];
                }
                continue;
            }
            if (isset($value['children'])) {
                foreach ($value['children'] as $k => $v) {
                    if ($v['key'] === $params['parentKey']) {
                        if (isset($v['children']) && $v['children'] !== []) {
                            $lastKey2 = array_pop($v['children'])['key'];
                            $keyArray2 = explode('-', $lastKey2);
                            $keyArray2[count($keyArray2) - 1]++;
                            $newKey2 = implode('-', $keyArray2);
                            $tree[$key]['children'][$k]['children'][count($v['children'])] = [
                                'title' => $params['title'],
                                'type'  => $params['title'],
                                'key'   => $newKey,
                            ];
                        } else {
                            $tree[$key]['children'][$k]['children'][] = [
                                'title' => $params['title'],
                                'type'  => $params['title'],
                                'key'   => $v['key'] . '-1',
                            ];
                        }
                        continue;
                    }
                }
            }
        }

        option([$title => $tree]);

        return response()->formatJson(true);
    }

    public function fixedCostTable(Request $request)
    {
        $params = $request->all();
        if (isset($params['time']) && !empty($params['time']) && $params['time'] !== '2019') {
            $title = 'fixedCostTree_' . $params['time'];
        } else {
            $title = 'fixedCostTree';
        }

        $tree = option($title);
        $result = [];
        $intFields = ['标准运营车辆数（辆）', '总客运量（人次）'];
        
        foreach ($tree as $key => $value) {
            $value['node'] = 1;
            if (isset($value['children'])) {
                $value['hasChildren'] = true;                
            }
            if ($value['amount']) {                           
                if (in_array($value['title'], $intFields, true)) {
                    $value['amount'] = number_format($value['amount'], 0);
                } else {
                    $value['amount'] = number_format($value['amount'], 2);
                }
            } else {
                $value['amount'] = 0;
            }
            $result[] = $value;
            if (isset($value['children'])) {                
                foreach ($value['children'] as $k => $v) {
                    $v['parent'] = $value['key'];
                    $v['amount'] = $v['amount'] ? number_format($v['amount'], 2) : 0.00;
                    $result[] = $v;
                }
            }
        }

        return response()->formatJson($result);
    }

    public function updateFixedCostTable(Request $request)
    {
        $params = $request->all();
        if (isset($params['time']) && !empty($params['time']) && $params['time'] !== '2019') {
            $title = 'fixedCostTree_' . $params['time'];
        } else {
            $title = 'fixedCostTree';
        }
        $paramsData = $params['paramsData'];
        foreach ($paramsData as $k => &$v) {
            $v['amount'] = (float) str_replace(',', '', $v['amount']);
        }        
        $tree = option($title);
        foreach ($paramsData as $key => $params) {
            $parent = array_key_exists('parent', $params) ? $params['parent'] : '';            
            foreach ($tree as $key2 => $value) {
                if ($value['key'] === $params['key']) {
                    $tree[$key2]['amount'] = $params['amount'];
                    $tree[$key2]['note'] = $params['note'];
                }
                if (isset($value['children'])) {
                    foreach ($value['children'] as $k => $v) {
                        if ($v['key'] === $params['key']) {
                            $tree[$key2]['children'][$k]['amount'] = $params['amount'];
                            $tree[$key2]['children'][$k]['note'] = $params['note'];
                        }
                    }
                }
            }

            // 有子项目的计算合计值
            if ($parent) {
                foreach ($tree as $key3 => $value) {
                    if ($value['key'] === $parent) {
                        $tree[$key3]['amount'] = array_sum(array_column($value['children'], 'amount'));
                    }
                }
            }
        }        
        // 特殊项计算
        $hyarr = ['一', '二', '三', '四', '五', '六', '七', '八', '九', '十', '十一', '十二', '十三', '十四', '十五', '十六', '十七', '十八', '十九', '二十'];        
        $millage = $count = $zkyamount = 0;
        $newArray = []; //用来存放都哪几项参与到客运总成本的计算
        foreach ($tree as $k => $v) {
            if ($v['type'] === '标准运营车里程（公里）') {
                $millage = (float) $v['amount'];
            }
            if ($v['type'] === '总客运量（人次）') {
                $count = (int) $v['amount'];
            }
            //判断哪几项参与到客运总成本的计算
            if ($arr = explode('、', $v['type'])) {
                if (count($arr) > 1) {
                    if ($arr[1] === '客运总成本（元）') {
                        if (in_array($arr[0], $hyarr)) {
                            //获取客运总成本是第几项                            
                            $index = array_keys($hyarr, $arr[0]); //下标                            
                            $newArray = array_slice($hyarr, 0, $index[0]);
                        }
                    }
                }
            }
        }
        //计算客运总成本
        foreach ($tree as $k => $v) {
            if ($arr = explode('、', $v['type'])) {
                if (count($arr) > 1) {
                    if (in_array($arr[0], $newArray)) {
                        $zkyamount = $zkyamount + (float) $v['amount'];
                    }
                }
            }
        }
        foreach ($tree as $k => $v) {
            if ($arr = explode('、', $v['type'])) {
                if (count($arr) > 1) {
                    if ($arr[1] === '客运总成本（元）') {
                        $tree[$k]['amount'] = (float) $zkyamount;;
                    }
                    if ($arr[1] === '每公里客运成本（元/公里）') {
                        $tree[$k]['amount'] = $millage != 0 ? number_format($zkyamount / $millage, 2, '.', '') : '';
                    }
                    if ($arr[1] === '单位人次客运成本（元/人次）') {
                        $tree[$k]['amount'] = $count !== 0 ? number_format($zkyamount / $count, 2, '.', '') : '';
                    }
                }
            }
        }        
        option([$title => $tree]);

        return response()->formatJson(true);
    }

    public function rebuildKeys($array)
    {
        if (!is_array($array)) {
            return $array;
        }
        $keys = implode('', array_keys($array));
        if (is_numeric($keys)) {
            $array = array_values($array);
        }
        $array = array_map([$this, 'rebuildKeys'], $array);

        return $array;
    }

    public function addCostKey(Request $request)
    {
        $params = $request->all();
        if (isset($params['title'])) {
            $title = trim($params['title']);
            $key = 'fixedCostTree_' . $title;
        } else {
            $key = 'fixedCostTree_' . date('Y');
        }
        //检测是否已经存在
        $id = DB::table('options')->where('key', $key)->value('id');
        if ($id) {
            return response()->formatJson('', '此客运成本表已经存在!');
        }
        //获取模板
        $value = DB::table('options')->where('key', 'fixedCostTreeTemplate')->value('value');
        //创建新的客运成本表
        $insertData = [
            'key'   => $key,
            'value' => $value,
        ];
        $result = DB::table('options')->insert($insertData);
        $msg = $result ? '添加成功' : '添加失败';
        return response()->formatJson($result, $msg);
    }

    public function getTreeKeyList()
    {
        $data = DB::table('options')
            ->where('key', 'like', 'fixedCostTree%')
            ->whereNotIn('key', ['fixedCostTreeTemplate'])
            ->orderByDesc('key')
            ->pluck('key')
            ->toArray();

        $result = [];
        foreach ($data as $k => $v) {
            $v = explode('_', $v);
            $title = $v[1] ?? '2019';
            $result[$k]['title'] = $title;
            $result[$k]['expand'] = false;
        }

        $result = $this->arraySort($result, 'title');
        // 默认选中年份
        $selectYear = '';
        foreach ($result as $key => &$value) {
            if ($key === 0) {
                $value['selected'] = true;
                $selectYear = $value['title'];
            }
        }

        return response()->formatJson(['selectYear' => $selectYear, 'data' => $result]);
    }

    /**
     * 二维数组根据某个字段排序
     *
     * @param  array  $array  要排序的数组
     * @param  string  $keys  要排序的键字段
     * @param  string  $sort  排序类型  SORT_ASC     SORT_DESC
     *
     * @return array 排序后的数组
     */
    public function arraySort(array $array, string $keys, $sort = SORT_DESC): array
    {
        $keysValue = [];
        foreach ($array as $k => $v) {
            $keysValue[$k] = $v[$keys];
        }
        array_multisort($keysValue, $sort, $array);

        return $array;
    }
}
